"""
Case Type   : 操作系统类-文件系统故障
Case Name   : gs_ctl启停时，备机注入故障系统文件系统 inode 资源耗尽
Create At   : 2021/7/19
Owner       : @wan005
Description :
    1、注入文件系统inode资源耗尽故障
    2、备节点上执行gs_ctl stop
    3、备节点上执行gs_ctl start
    4、清理故障，gs_ctl start
    5、执行TPCC
    6、检查数据一致性
    7、恢复环境
Expect      :
    1、故障注入成功
    2、stop成功
    3、start失败
    4、清理恢复成功 start成功
    5、执行TPCC成功
    6、数据一致
    7、恢复环境
History     :
    Modified by @wan005 2022/4/26: 优化期望结果
"""
import time
import unittest

from testcase.utils.ComThread import ComThread
from testcase.utils.Common import Common
from testcase.utils.CommonSH import CommonSH
from testcase.utils.CommonSH import RestartDbCluster
from testcase.utils.Constant import Constant
from testcase.utils.Logger import Logger
from yat.test import Node, macro


class ReliabilityFileSystem(unittest.TestCase):
    nodes = ("PrimaryDbUser", "Standby1DbUser", "Standby2DbUser")

    @RestartDbCluster(*nodes)
    def setUp(self):
        self.log = Logger()
        self.primary_sh = CommonSH(self.nodes[0])
        self.sta1_sh = CommonSH(self.nodes[1])
        self.primary_root_node = Node(node="PrimaryRoot")
        self.sta1_root_node = Node(node="Standby1Root")
        self.constant = Constant()
        self.com = Common()
        self.log.info("setUp-实例化:ok")

        self.log.info("Opengauss_Reliability_OS_File_System_Case013:开始执行")
        self.file_name = macro.DB_INSTANCE_PATH
        self.inject_cmd = f"rfile_ideplenish_workmode " \
                          f"(filename, workmode) " \
                          f"values ({self.file_name}, fore)"
        self.clean_cmd = f"rfile_ideplenish_workmode where " \
                         f"filename={self.file_name} and workmode=fore"

    def test_main(self):
        try:
            self.log.info("步骤1:备节点注入文件系统inode资源故障")
            self.log.info("注入故障")
            session = ComThread(self.com.cfe_inject,
                                args=(self.sta1_root_node,
                                      self.inject_cmd))
            session.setDaemon(True)
            session.start()

            session.join(60 * 50)
            result = session.get_result()
            self.log.info("故障注入结果")
            self.log.info(result)
            self.assertIn("successful execution", result)

            self.log.info("步骤2:备节点上执行gs_ctl stop 成功")
            result = self.sta1_sh.executeGsctl("stop",
                                               "server stopped",
                                               get_detail=True)
            self.log.info(result)
            self.assertNotIn("No space left on device", result)
            self.assertIn("server stopped", result)

            self.log.info("步骤3:备节点上执行gs_ctl start 失败")
            result = self.sta1_sh.executeGsctl("start",
                                               "server started",
                                               param="-M standby",
                                               get_detail=True)
            self.log.info(result)
            self.assertIn("No space left on device", result)
            self.assertNotIn("server started", result)

            self.log.info("清除故障")
            result = self.com.cfe_clean(self.sta1_root_node,
                                        self.clean_cmd)
            self.log.info(result)
            self.assertIn("successful execution", result)

        finally:
            self.log.info("清除故障")
            result = self.com.cfe_clean(self.sta1_root_node,
                                        self.clean_cmd)
            self.log.info(result)
            self.assertIn("successful execution", result)

            result = self.primary_sh.stopDbCluster(get_detail=True)
            self.log.info(result)
            result = self.primary_sh.startDbCluster(get_detail=True)
            self.log.info(result)

        self.log.info("build 1备机")
        result = self.sta1_sh.executeGsctl("build",
                                           "server started",
                                           param="-b full",
                                           get_detail=True)
        self.log.info(result)
        self.assertIn("server started", result)

        db_status = self.primary_sh.getDbClusterStatus("detail")
        self.log.info(db_status)
        self.assertTrue("Degraded" in db_status or "Normal" in db_status)

        self.log.info("步骤5:运行TPCC")
        result = self.com.startTPCC(self.primary_root_node, macro.TPCC_PATH)
        self.log.info(result)
        self.assertIn(self.constant.TPCC_SUCCESS_MSG, result)

        self.log.info('检查主备是否同步')
        time.sleep(10)
        self.log.info('获取节点数量')
        node_num = self.primary_sh.get_node_num()
        res = self.primary_sh.check_location_consistency("primary", node_num)
        self.assertTrue(res)

        self.log.info('步骤6:检查数据一致性')
        nodes = (Node(self.nodes[0]), Node(self.nodes[1]),
                 Node(self.nodes[2]))
        flag = self.com.check_data_sample_by_all(r'\d', *nodes)
        self.assertTrue(flag)
        table_dict = self.com.format_sql_result(
            self.primary_sh.executDbSql(r'\d'))
        table_name = table_dict.get('Name')
        for name in table_name:
            select_sql = f'select count(*) from {name};'
            flag = self.com.check_data_sample_by_all(select_sql, *nodes)
            self.assertTrue(flag)

    def tearDown(self):
        self.log.info("步骤7:环境清理")
        result = self.com.cfe_clean(self.sta1_root_node,
                                    self.clean_cmd)
        self.log.info(result)
        self.assertIn("successful execution", result)
        self.log.info("故障已清理")
        self.log.info("Opengauss_Reliability_OS_File_System_Case013:执行完成")
